<template><div><p>本文档最新版为 <a href="https://learnku.com/docs/laravel/10.x" target="_blank" rel="noopener noreferrer">10.x</a>，旧版本可能放弃维护，推荐阅读最新版！</p>
<h2 id="laravel-服务容器解析" tabindex="-1"><a class="header-anchor" href="#laravel-服务容器解析"><span>Laravel 服务容器解析</span></a></h2>
<ul>
<li><a href="#introduction">简介</a></li>
<li><a href="#binding">绑定</a>
<ul>
<li><a href="#binding-basics">绑定基础</a></li>
<li><a href="#binding-interfaces-to-implementations">绑定接口实现</a></li>
<li><a href="#contextual-binding">上下文绑定</a></li>
<li><a href="#tagging">标记</a></li>
</ul>
</li>
<li><a href="#resolving">解析</a>
<ul>
<li><a href="#the-make-method">Make 方法</a></li>
<li><a href="#automatic-injection">自动注入</a></li>
</ul>
</li>
<li><a href="#container-events">容器事件</a></li>
<li><a href="#psr-11">PSR-11</a></li>
</ul>
<h2 id="简介" tabindex="-1"><a class="header-anchor" href="#简介"><span>简介</span></a></h2>
<p>Laravel 服务容器是用于管理类的依赖和执行依赖注入的工具。依赖注入这个花俏名词实质上是指：类的依赖项通过构造函数，或者某些情况下通过「setter」方法「注入」到类中。</p>
<p>来看一个简单的例子:</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Controllers</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>User</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Repositories<span class="token punctuation">\</span>UserRepository</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Controllers<span class="token punctuation">\</span>Controller</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">UserController</span> <span class="token keyword">extends</span> <span class="token class-name">Controller</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 用户存储库的实现。</span>
<span class="line">     *</span>
<span class="line">     * <span class="token keyword">@var</span> <span class="token class-name">UserRepository</span></span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">protected</span> <span class="token variable">$users</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 创建新的控制器实例。</span>
<span class="line">     *</span>
<span class="line">     * <span class="token keyword">@param</span>  <span class="token class-name">UserRepository</span>  <span class="token parameter">$users</span></span>
<span class="line">     * <span class="token keyword">@return</span> <span class="token class-name"><span class="token keyword">void</span></span></span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">__construct</span><span class="token punctuation">(</span><span class="token class-name type-declaration">UserRepository</span> <span class="token variable">$users</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">users</span> <span class="token operator">=</span> <span class="token variable">$users</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 显示指定用户的 profile。</span>
<span class="line">     *</span>
<span class="line">     * <span class="token keyword">@param</span>  <span class="token class-name"><span class="token keyword">int</span></span>  <span class="token parameter">$id</span></span>
<span class="line">     * <span class="token keyword">@return</span> <span class="token class-name">Response</span></span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">show</span><span class="token punctuation">(</span><span class="token variable">$id</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token variable">$user</span> <span class="token operator">=</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">users</span><span class="token operator">-></span><span class="token function">find</span><span class="token punctuation">(</span><span class="token variable">$id</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">return</span> <span class="token function">view</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'user.profile'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'user'</span> <span class="token operator">=></span> <span class="token variable">$user</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>在这个例子中，控制器 <code v-pre>UserController</code> 需要从数据源中获取 users 。因此，我们要<strong>注入</strong>可以获取 users 的服务。在这种情况下，<code v-pre>UserRepository</code> 可能是使用 <a href="https://learnku.com/docs/laravel/5.5/eloquent" target="_blank" rel="noopener noreferrer">Eloquent</a> 从数据库中获取 user 信息。因为 Repository 是通过 <code v-pre>UserRepository</code> 注入的，所以我们可以轻易地将其切换为另一个实现。这种注入方式的便利之处还体现在当我们为应用编写测试时，我们还可以轻松地「模拟」或创建 <code v-pre>UserRepository</code> 的虚拟实现。</p>
<p>想要构建强大的大型应用，至关重要的一件事是：要深刻的理解 Laravel 服务容器。当然，为 Laravel 的核心代码做出贡献也一样。</p>
<h2 id="绑定" tabindex="-1"><a class="header-anchor" href="#绑定"><span>绑定</span></a></h2>
<h3 id="绑定基础" tabindex="-1"><a class="header-anchor" href="#绑定基础"><span>绑定基础</span></a></h3>
<p>因为几乎所有服务容器都是在 <a href="https://learnku.com/docs/laravel/5.5/providers" target="_blank" rel="noopener noreferrer">服务提供器</a> 中注册绑定的，所以文档中大多数例子都是使用了在服务提供器中绑定的容器。</p>
<blockquote>
<p>{tip} 如果类没有依赖任何接口，就没有必要将类绑定到容器中。容器不需要指定如何构建这些对象，因为它可以使用反射自动解析这些对象。</p>
</blockquote>
<h4 id="简单绑定" tabindex="-1"><a class="header-anchor" href="#简单绑定"><span>简单绑定</span></a></h4>
<p>在服务提供器中，你可以通过 <code v-pre>$this-&gt;app</code> 属性访问容器。我们可以通过 <code v-pre>bind</code> 方法注册绑定，传递我们想要注册的类或接口名称再返回类的实例的 <code v-pre>Closure</code> ：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">app</span><span class="token operator">-></span><span class="token function">bind</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'HelpSpot\API'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token variable">$app</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name class-name-fully-qualified">HelpSpot<span class="token punctuation">\</span>API</span><span class="token punctuation">(</span><span class="token variable">$app</span><span class="token operator">-></span><span class="token function">make</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'HttpClient'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>注意，我们接受容器本身作为解析器的参数。然后，我们可以使用容器来解析正在构建的对象的子依赖。</p>
<h4 id="绑定一个单例" tabindex="-1"><a class="header-anchor" href="#绑定一个单例"><span>绑定一个单例</span></a></h4>
<p><code v-pre>singleton</code> 方法将类或接口绑定到只能解析一次的容器中。绑定的单例被解析后，相同的对象实例会在随后的调用中返回到容器中：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">app</span><span class="token operator">-></span><span class="token function">singleton</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'HelpSpot\API'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token variable">$app</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name class-name-fully-qualified">HelpSpot<span class="token punctuation">\</span>API</span><span class="token punctuation">(</span><span class="token variable">$app</span><span class="token operator">-></span><span class="token function">make</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'HttpClient'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="绑定实例" tabindex="-1"><a class="header-anchor" href="#绑定实例"><span>绑定实例</span></a></h4>
<p>你也可以使用 <code v-pre>instance</code> 方法将现有对象实例绑定到容器中。给定的实例会始终在随后的调用中返回到容器中：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$api</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name class-name-fully-qualified">HelpSpot<span class="token punctuation">\</span>API</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">HttpClient</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">app</span><span class="token operator">-></span><span class="token function">instance</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'HelpSpot\API'</span><span class="token punctuation">,</span> <span class="token variable">$api</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="绑定初始数据" tabindex="-1"><a class="header-anchor" href="#绑定初始数据"><span>绑定初始数据</span></a></h4>
<p>当你有一个类不仅需要接受一个注入类，还需要注入一个基本值（比如整数）。你可以使用上下文绑定来轻松注入你的类需要的任何值：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">app</span><span class="token operator">-></span><span class="token function">when</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'App\Http\Controllers\UserController'</span><span class="token punctuation">)</span></span>
<span class="line">          <span class="token operator">-></span><span class="token function">needs</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'$variableName'</span><span class="token punctuation">)</span></span>
<span class="line">          <span class="token operator">-></span><span class="token function">give</span><span class="token punctuation">(</span><span class="token variable">$value</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="绑定接口到实现" tabindex="-1"><a class="header-anchor" href="#绑定接口到实现"><span>绑定接口到实现</span></a></h3>
<p>服务容器有一个强大的功能，就是将接口绑定到给定实现。例如，如果我们有一个 <code v-pre>EventPusher</code> 接口和一个 <code v-pre>RedisEventPusher</code> 实现。编写完接口的 <code v-pre>RedisEventPusher</code> 实现后，我们就可以在服务容器中注册它，像这样：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">app</span><span class="token operator">-></span><span class="token function">bind</span><span class="token punctuation">(</span></span>
<span class="line">    <span class="token string single-quoted-string">'App\Contracts\EventPusher'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token string single-quoted-string">'App\Services\RedisEventPusher'</span></span>
<span class="line"><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这么做相当于告诉容器：当一个类需要实现 <code v-pre>EventPusher</code> 时，应该注入 <code v-pre>RedisEventPusher</code>。现在我们就可以在构造函数或者任何其他通过服务容器注入依赖项的地方使用类型提示注入 <code v-pre>EventPusher</code> 接口：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Contracts<span class="token punctuation">\</span>EventPusher</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 创建一个新的类实例</span>
<span class="line"> *</span>
<span class="line"> * <span class="token keyword">@param</span>  <span class="token class-name">EventPusher</span>  <span class="token parameter">$pusher</span></span>
<span class="line"> * <span class="token keyword">@return</span> <span class="token class-name"><span class="token keyword">void</span></span></span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">__construct</span><span class="token punctuation">(</span><span class="token class-name type-declaration">EventPusher</span> <span class="token variable">$pusher</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">pusher</span> <span class="token operator">=</span> <span class="token variable">$pusher</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="上下文绑定" tabindex="-1"><a class="header-anchor" href="#上下文绑定"><span>上下文绑定</span></a></h3>
<p>有时候，你可能有两个类使用了相同的接口，但你希望每个类都能注入不同的实现。例如，两个控制器可能需要依赖不同的 <code v-pre>Illuminate\Contracts\Filesystem\Filesystem</code> <a href="https://learnku.com/docs/laravel/5.5/contracts" target="_blank" rel="noopener noreferrer">契约</a> 实现。 Laravel 提供了一个简单、优雅的接口来定义这个行为：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Storage</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Controllers<span class="token punctuation">\</span>PhotoController</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Controllers<span class="token punctuation">\</span>VideoController</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Contracts<span class="token punctuation">\</span>Filesystem<span class="token punctuation">\</span>Filesystem</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">app</span><span class="token operator">-></span><span class="token function">when</span><span class="token punctuation">(</span><span class="token class-name static-context">PhotoController</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">)</span></span>
<span class="line">          <span class="token operator">-></span><span class="token function">needs</span><span class="token punctuation">(</span><span class="token class-name static-context">Filesystem</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">)</span></span>
<span class="line">          <span class="token operator">-></span><span class="token function">give</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">              <span class="token keyword">return</span> <span class="token class-name static-context">Storage</span><span class="token operator">::</span><span class="token function">disk</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'local'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">          <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">app</span><span class="token operator">-></span><span class="token function">when</span><span class="token punctuation">(</span><span class="token class-name static-context">VideoController</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">)</span></span>
<span class="line">          <span class="token operator">-></span><span class="token function">needs</span><span class="token punctuation">(</span><span class="token class-name static-context">Filesystem</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">)</span></span>
<span class="line">          <span class="token operator">-></span><span class="token function">give</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">              <span class="token keyword">return</span> <span class="token class-name static-context">Storage</span><span class="token operator">::</span><span class="token function">disk</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'s3'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">          <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="标记" tabindex="-1"><a class="header-anchor" href="#标记"><span>标记</span></a></h3>
<p>有时候，你可能需要解析某个「分类」下的所有绑定。例如，你正在构建一个报表的聚合器，它接收一个包含不同 <code v-pre>Report</code> 接口实现的数组。注册了 <code v-pre>Report</code> 实现后，你可以使用 <code v-pre>tag</code> 方法为其分配标签：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">app</span><span class="token operator">-></span><span class="token function">bind</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'SpeedReport'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">//</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">app</span><span class="token operator">-></span><span class="token function">bind</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'MemoryReport'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">//</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">app</span><span class="token operator">-></span><span class="token function">tag</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'SpeedReport'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'MemoryReport'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'reports'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>服务被标记后，你可以通过 <code v-pre>tagged</code> 方法轻松地将它们全部解析：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">app</span><span class="token operator">-></span><span class="token function">bind</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'ReportAggregator'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token variable">$app</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">ReportAggregator</span><span class="token punctuation">(</span><span class="token variable">$app</span><span class="token operator">-></span><span class="token function">tagged</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'reports'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="解析" tabindex="-1"><a class="header-anchor" href="#解析"><span>解析</span></a></h2>
<h4 id="make-方法" tabindex="-1"><a class="header-anchor" href="#make-方法"><span><code v-pre>make</code> 方法</span></a></h4>
<p>你可以使用 <code v-pre>make</code> 方法将容器中的类实例解析出来。<code v-pre>make</code> 方法接受要解析的类或接口的名称：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$api</span> <span class="token operator">=</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">app</span><span class="token operator">-></span><span class="token function">make</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'HelpSpot\API'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>如果你的代码处于不能访问 <code v-pre>$app</code> 变量的位置，你可以使用全局的辅助函数 <code v-pre>resolve</code>：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$api</span> <span class="token operator">=</span> <span class="token function">resolve</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'HelpSpot\API'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>如果你的某些类的依赖项不能通过容器去解析，那你可以通过将它们作为关联数组传递到 <code v-pre>makeWith</code> 方法来注入它们。</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$api</span> <span class="token operator">=</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">app</span><span class="token operator">-></span><span class="token function">makeWith</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'HelpSpot\API'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'id'</span> <span class="token operator">=></span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h4 id="自动注入" tabindex="-1"><a class="header-anchor" href="#自动注入"><span>自动注入</span></a></h4>
<p>你可以简单地使用「类型提示」的方式在由容器解析的类的构造函数中添加依赖项，包括 <a href="https://learnku.com/docs/laravel/5.5/controllers" target="_blank" rel="noopener noreferrer">控制器</a>、<a href="https://learnku.com/docs/laravel/5.5/events" target="_blank" rel="noopener noreferrer">事件监听器</a>、<a href="https://learnku.com/docs/laravel/5.5/queues" target="_blank" rel="noopener noreferrer">队列任务</a>、<a href="https://learnku.com/docs/laravel/5.5/middleware" target="_blank" rel="noopener noreferrer">中间件</a> 等。 事实上，这是你的大多数对象也应该由容器解析。</p>
<p>例如，你可以在控制器的构造函数中对应用程序定义的 Repository 使用类型提示。Repository 会被自动解析并注入到类中：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Controllers</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Users<span class="token punctuation">\</span>Repository</span> <span class="token keyword">as</span> UserRepository<span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">UserController</span> <span class="token keyword">extends</span> <span class="token class-name">Controller</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 用户存储库实例。</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">protected</span> <span class="token variable">$users</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 创建一个新的控制器实例。</span>
<span class="line">     *</span>
<span class="line">     * <span class="token keyword">@param</span>  <span class="token class-name">UserRepository</span>  <span class="token parameter">$users</span></span>
<span class="line">     * <span class="token keyword">@return</span> <span class="token class-name"><span class="token keyword">void</span></span></span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">__construct</span><span class="token punctuation">(</span><span class="token class-name type-declaration">UserRepository</span> <span class="token variable">$users</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">users</span> <span class="token operator">=</span> <span class="token variable">$users</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 显示指定 ID 的用户信息。</span>
<span class="line">     *</span>
<span class="line">     * <span class="token keyword">@param</span>  <span class="token class-name"><span class="token keyword">int</span></span>  <span class="token parameter">$id</span></span>
<span class="line">     * <span class="token keyword">@return</span> <span class="token class-name">Response</span></span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">show</span><span class="token punctuation">(</span><span class="token variable">$id</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">//</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="容器事件" tabindex="-1"><a class="header-anchor" href="#容器事件"><span>容器事件</span></a></h2>
<p>每当服务容器解析一个对象时触发一个事件。你可以使用 <code v-pre>resolving</code> 方法监听这个事件：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">app</span><span class="token operator">-></span><span class="token function">resolving</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token variable">$object</span><span class="token punctuation">,</span> <span class="token variable">$app</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// 当容器解析任何类型的对象时调用...</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">app</span><span class="token operator">-></span><span class="token function">resolving</span><span class="token punctuation">(</span><span class="token class-name class-name-fully-qualified static-context">HelpSpot<span class="token punctuation">\</span>API</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token variable">$api</span><span class="token punctuation">,</span> <span class="token variable">$app</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// 当容器解析类型为「HelpSpot\API」的对象时调用...</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如你所见，被解析的对象会被传递给回调中，让你在对象被传递出去之前可以在对象上设置任何属性。</p>
<h2 id="psr-11" tabindex="-1"><a class="header-anchor" href="#psr-11"><span>PSR-11</span></a></h2>
<p>Laravel 的服务容器实现了 <a href="https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-11-container.md" target="_blank" rel="noopener noreferrer">PSR-11</a> 接口。因此，你可以使用 PSR-11容器接口类型提示来获取 Laravel 容器的实例：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Psr<span class="token punctuation">\</span>Container<span class="token punctuation">\</span>ContainerInterface</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">ContainerInterface</span> <span class="token variable">$container</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token variable">$service</span> <span class="token operator">=</span> <span class="token variable">$container</span><span class="token operator">-></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Service'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token comment">//</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p>{note} 如果标签没有明确绑定到容器中，那么调用 <code v-pre>get</code> 方法时会抛出异常。</p>
</blockquote>
<h2 id="译者署名" tabindex="-1"><a class="header-anchor" href="#译者署名"><span>译者署名</span></a></h2>
<table>
<thead>
<tr>
<th>用户名</th>
<th>头像</th>
<th>职能</th>
<th>签名</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="http://www.jianshu.com/u/7fdb641c0d01" target="_blank" rel="noopener noreferrer">@kair</a></td>
<td><img src="https://cdn.learnku.com/uploads/avatars/18390_1502954686.jpeg?imageView2/1/w/100/h/100" alt="100"></td>
<td>翻译</td>
<td><a href="https://github.com/JKair" target="_blank" rel="noopener noreferrer">@kair</a></td>
</tr>
<tr>
<td><a href="https://learnku.com/users/5350" target="_blank" rel="noopener noreferrer">@JokerLinly</a></td>
<td><img src="https://cdn.learnku.com/uploads/avatars/5350_1481857380.jpg" alt="5350_1481857380.jpg"></td>
<td>Review</td>
<td>Stay Hungry. Stay Foolish.</td>
</tr>
</tbody>
</table>
<hr>
<blockquote>
<p>{note} 欢迎任何形式的转载，但请务必注明出处，尊重他人劳动共创开源社区。</p>
<p>转载请注明：本文档由 Laravel China 社区 <a href="https://laravel-china.org/" target="_blank" rel="noopener noreferrer">laravel-china.org</a> 组织翻译，详见 <a href="https://learnku.com/laravel/t/5756/laravel-55-document-translation-call-come-and-join-the-translation" target="_blank" rel="noopener noreferrer">翻译召集帖</a>。</p>
<p>文档永久地址： <a href="https://learnku.com/docs/laravel" target="_blank" rel="noopener noreferrer">《Laravel 中文文档》</a></p>
</blockquote>
</div></template>


